#!/bin/bash -e

# Based on package-lint/run-tests.sh

# * Defaults

MAIN_FILE="../org-super-agenda.el"
TEST_FILE="test.el"
command=run_tests

# Byte compile, failing on byte compiler errors, or on warnings unless ignored
if [ -n "${EMACS_LINT_IGNORE+x}" ]; then
    ERROR_ON_WARN=nil
else
    ERROR_ON_WARN=t
fi

# Just disable the errors
ERROR_ON_WARN=nil
EMACS_LINT_IGNORE=t

EMACS="${EMACS:=emacs}"

# NOTE: The code in this variable does initialize the package system, but
# it does so using e.g. ~/.emacs.d/elpa, not the project .cask directory,
# so it should not be used except for e.g. debugging.  Failure to
# understand this may lead to version confusion and hair-pulling.

# INIT_PACKAGE_EL="(progn
# (require 'package)
# (setq package-archives '((\"gnu\" . \"https://elpa.gnu.org/packages/\")
#                          (\"melpa\" . \"https://melpa.org/packages/\")))
# (package-initialize)
# (setq debug-on-error t))"

# PACKAGES_NEEDED="
# (cl-loop for package in '(ht f s dash)
#          unless (package-installed-p package)
#          do (package-install package))"

# # Since package-install refuses to install a package that's already
# # installed, and package-reinstall can't delete the built-in Org
# # package, we have to fool it into thinking Org isn't installed by
# # binding package--builtins and package--builtin-versions to nil.
# UPDATE_ORG_IF_NEEDED="
# (unless (version<= \"9.0\" (org-version))
#   (let (package--builtins package--builtin-versions)
#     (package-install 'org)))"

# Workaround weird indentation bug in Emacs shell-script-mode.  It
# sees the single-quotes in the vars above and thinks that there is an
# open single-quoted string, and it cascades down and affects the
# indentation later in the file.  Apparently we need to keep an even
# number of single-quotes.  But that's not all: it's also related to
# whether the variable itself contains a newline.  Weird.
FAKE_VAR="
(something 'something)"

# * Functions

function debug {
    if [[ $debug ]]
    then
        function debug {
            echo "DEBUG: $@" >&2
        }
        debug "$@"
    else
        function debug {
            true
        }
    fi
}
function die {
    echo "$@" >&2
    exit 1
}
function usage {
    cat <<EOF
$0 [OPTIONS] ...?

This does something cool!

Options
  -d, --debug  Print debug info
  -h, --help   I need somebody!
EOF
}

function refresh {
    debug "REFRESHING..."

    # Refresh package archives, because the test suite needs to see at least
    # package-lint and cl-lib.
    "$EMACS" -Q -batch \
             --eval "(unless (package-installed-p 'cl-lib) (package-install 'cl-lib))" \
             --eval "$PACKAGES_NEEDED"
}


function byte_compile {
    debug "BYTE-COMPILING..."

    "$EMACS" -Q -batch \
             -l $MAIN_FILE \
             --eval "(setq byte-compile-error-on-warn ${ERROR_ON_WARN})" \
             -f batch-byte-compile \
             $MAIN_FILE
}
function lint {
    # Lint ourselves
    # Lint failures are ignored if EMACS_LINT_IGNORE is defined, so that lint
    # failures on Emacs 24.2 and below don't cause the tests to fail, as these
    # versions have buggy imenu that reports (defvar foo) as a definition of foo.

    debug "LINTING..."

    "$EMACS" -Q -batch \
             -l $MAIN_FILE \
             -f package-lint-batch-and-exit \
             $MAIN_FILE || [ -n "${EMACS_LINT_IGNORE+x}" ]
}

function run_tests {
    debug "TESTING..."

    "$EMACS" -Q -batch \
             --eval "(message \"Org version: %s\" (org-version))" \
             -l $MAIN_FILE \
             -l $TEST_FILE \
             -f org-super-agenda-test--load-results \
             -f ert-run-tests-batch-and-exit
}

function update {
    debug "UPDATING..."

    "$EMACS" -Q -batch \
             --eval "(message \"Org version: %s\" (org-version))" \
             -l $MAIN_FILE \
             -l $TEST_FILE \
             --eval "(with-current-buffer (find-file-noselect \"test.el\") (org-super-agenda--test-update-all-tests :force t))"
}

# * Args

args=$(getopt -n "$0" -o dhU -l debug,help,update -- "$@") || exit 1
eval set -- "$args"

while true
do
    case "$1" in
        -d|--debug)
            debug=true
            ;;
        -h|--help)
            usage
            exit
            ;;
        -U|--update)
            command=update
            ;;
        --)
            # Remaining args
            shift
            rest=("$@")
            break
            ;;
    esac

    shift
done

debug "ARGS: $args"
debug "Remaining args: ${rest[@]}"

# * Main

# Print date/time information since Travis seems to be an hour off
debug=t
debug "Local time: $(date)"
debug "UTC: $(date --utc)"

# Ensure we run from the test directory
if [[ $0 = "test/run" ]]
then
    cd test || die "Can't change to test directory."
fi

case $command in
    update)
        update
        ;;
    run_tests)
        run_tests
        ;;
esac
